package com.zy.view;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.LinearInterpolator;

import java.util.ArrayList;
import java.util.List;

//堆
//31个元素
public class HeapV2View extends View {


    public HeapV2View(Context context) {
        super(context);
        init(context);
    }


    public HeapV2View(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public HeapV2View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    public HeapV2View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context);
    }

    Paint nodePaint;
    Paint textPaint;
    Paint indexPaint;
    Paint assistLinePaint;

    private void init(Context context) {
        nodePaint = new Paint();
        nodePaint.setColor(Color.WHITE);

        textPaint = new Paint();
        //设置文本大小
        textPaint.setTextSize(72);
        //设置文本对齐方式
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setColor(Color.RED);

        indexPaint = new Paint();
        //设置文本大小
        indexPaint.setTextSize(36);
        //设置文本对齐方式
        indexPaint.setTextAlign(Paint.Align.CENTER);
        indexPaint.setColor(Color.BLUE);

        assistLinePaint = new Paint();
        assistLinePaint.setColor(Color.WHITE);
        DashPathEffect effects = new DashPathEffect(new float[]{5, 5, 5, 5}, 10);
        assistLinePaint.setPathEffect(effects);

    }

    boolean buildUINode = false;
    List<HeapUINodeV2> uiNodeV2List = new ArrayList<>();

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d("HeapV2View", "" + getWidth() + " " + getHeight());
        int height = getHeight();

        int baseX = getWidth() / 2;
        int baseY = 100;

        drawAssistLineV2(canvas, 0, baseX, baseY);

        if (!buildUINode) {
            buildHeapNodeUIList(baseX, baseY);
            buildUINode = true;
        }

        for (int i = 0; i < uiNodeV2List.size(); i++) {
            uiNodeV2List.get(i).drawNode(canvas, i);
        }
    }

    public void setLineLength(int lineLength) {
        this.lineLength = lineLength;
    }

    int lineLength = 200;
    int baseLineWidth = 500;

    int radius = 50;
    List<Integer> assistLineList = new ArrayList<>();

    int maxDepth = 4;

    private void drawAssistLineV2(Canvas canvas, int depth, int centerX, int centerY) {
        if (depth > maxDepth) {
            return;
        }

        //指数
        int curLineWidth = (int) (baseLineWidth / (Math.pow(2, depth)));
        //画辅助线
        if (depth < maxDepth) {
            canvas.drawLine(centerX, centerY, centerX - curLineWidth, centerY + lineLength, assistLinePaint);
            canvas.drawLine(centerX, centerY, centerX + curLineWidth, centerY + lineLength, assistLinePaint);
        }
        //左
        drawAssistLineV2(canvas, depth + 1, centerX - curLineWidth, centerY + lineLength);
        drawAssistLineV2(canvas, depth + 1, centerX + curLineWidth, centerY + lineLength);
    }

    private void buildHeapNodeUIList(int centerX, int centerY) {
        int depth = 0;

        HeapUINodeV2 rootNode = new HeapUINodeV2(centerX, centerY);
        uiNodeV2List.add(rootNode);

        List<HeapUINodeV2> buildParentList = new ArrayList<>();
        buildParentList.add(rootNode);
        List<HeapUINodeV2> buildChildList = new ArrayList<>();
        do {

            HeapUINodeV2 nodeV2 = buildParentList.remove(0);
            //指数
            int curLineWidth = (int) (baseLineWidth / (Math.pow(2, depth)));

            //左
            HeapUINodeV2 leftNode = new HeapUINodeV2(nodeV2.centerX - curLineWidth, nodeV2.centerY + lineLength);
            buildChildList.add(leftNode);
            uiNodeV2List.add(leftNode);

            //右
            HeapUINodeV2 rightNode = new HeapUINodeV2(nodeV2.centerX + curLineWidth, nodeV2.centerY + lineLength);
            buildChildList.add(rightNode);
            uiNodeV2List.add(rightNode);


            if (buildParentList.size() == 0) {
                depth++;

                buildParentList.addAll(buildChildList);
                buildChildList.clear();
            }
        } while (depth < maxDepth);
    }

    private void drawAssistLine(int depth, Canvas canvas, int centerX, int centerY) {
        if (!assistLineList.contains(depth)) {
            assistLineList.add(depth);
            canvas.drawLine(0, centerY, getWidth(), centerY, assistLinePaint);
        }
    }


    private class HeapUINodeV2 {
        float centerX;
        float centerY;

        private float aniX = 0;
        private float aniY = 0;

        public HeapUINodeV2(float centerX, float centerY) {
            this.centerX = centerX;
            this.centerY = centerY;
        }

        void moveTo(float percentage, HeapUINodeV2 target) {
            float disX = target.centerX - centerX;
            aniX = disX * percentage;

            float disY = target.centerY - centerY;
            aniY = disY * percentage;
        }

        void reset() {
            aniX = 0;
            aniY = 0;
        }


        void drawNode(Canvas canvas, int index) {
            if (opIndexList.contains(index)) {
                nodePaint.setColor(Color.YELLOW);
                textPaint.setColor(Color.BLACK);
            } else {
                nodePaint.setColor(Color.WHITE);
                textPaint.setColor(Color.RED);
            }

            Log.d("ZYDebug", "" + sortedIndex);
            if (sortedIndex.contains(index)) {
                nodePaint.setColor(Color.GREEN);
                textPaint.setColor(Color.WHITE);
            }
            canvas.drawCircle(centerX + aniX, centerY + aniY, radius, nodePaint);
            //drawIndexCenter(canvas, centerX, centerY, "" + index);
            drawTextCenter(canvas, (centerX + aniX), (centerY + aniY), "" + dataS[index]);
        }
    }


    private void drawIndexCenter(Canvas canvas, float centerX, float centerY, String text) {
        //计算基线坐标
        float baseLineY = getBaseLineY(indexPaint, centerY + radius - 20);
        canvas.drawText(text, centerX, baseLineY, indexPaint);
    }

    private void drawTextCenter(Canvas canvas, float centerX, float centerY, String text) {
        //计算基线坐标
        float baseLineY = getBaseLineY(textPaint, centerY);
        canvas.drawText(text, centerX, baseLineY, textPaint);
    }


    private float getBaseLineY(Paint textPaint, float centerY) {
        Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
        return centerY + (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent;
    }


    int[] dataS;
    List<Integer> opIndexList;
    List<Integer> sortedIndex;

    public void setData(int[] dataS, List<Integer> opIndexList, List<Integer> sortedIndex) {
        this.dataS = dataS;
        this.opIndexList = opIndexList;
        this.sortedIndex = sortedIndex;
        invalidate();
    }

    private int getData(List<Integer> path) {
        //02222
        int index = 0;
        for (Integer p : path) {
            if (p == 1) {
                index = index * 2 + 1;
            } else if (p == 2) {
                index = index * 2 + 2;
            }
        }

        return dataS[index];
    }

    public void moveChange(int changeFIndex, int changeSIndex, AniListener aniListener) {
        HeapUINodeV2 firstNode = uiNodeV2List.get(changeFIndex);
        HeapUINodeV2 secondNode = uiNodeV2List.get(changeSIndex);

        ValueAnimator mAnimator = ValueAnimator.ofFloat(0, 1);
        mAnimator.setDuration(100);
        mAnimator.setInterpolator(new LinearInterpolator());
        mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //时间流,必须是线性的
                float percentage = (float) animation.getAnimatedValue();
                firstNode.moveTo(percentage, secondNode);
                secondNode.moveTo(percentage, firstNode);

                invalidate();
            }
        });
        mAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation, boolean isReverse) {
                super.onAnimationEnd(animation, isReverse);
                firstNode.reset();
                secondNode.reset();
                aniListener.aniEnd();
            }
        });
        mAnimator.start();
    }

    public interface AniListener {

        void aniEnd();
    }
}
